﻿using Microsoft.Extensions.Configuration;
using NP.BPMReportPlatform.BPMPlatform;
using NP.BPMReportPlatform.DBHelper;
using NP.BPMReportPlatform.Entities.BPM_Business;
using NP.BPMReportPlatform.Entities.BPM_Business.DailyCloseBook;
using NP.BPMReportPlatform.Entities.BPM_Business;
using NP.BPMReportPlatform.Entities.BPM_Engine;
using NP.BPMReportPlatform.Entities.BPM_Platform;
using NP.BPMReportPlatform.Reports.DailyCloseBook.Dtos;
using NP.BPMReportPlatform.Reports.MaterialCheckPlanChange.Dtos;
using NP.BPMReportPlatform.Utilities;
using NP.BPMReportPlatform.Utils;
using NP.Enterprise.Utils.Http;
using NPOI.SS.Formula.Functions;
using Serilog;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using System.Linq;

namespace NP.BPMReportPlatform.Reports.MaterialCheckPlanChange
{
    public class MaterialCheckPlanChangeService : BPMReportPlatformAppService, IMaterialCheckPlanChangeService
    {
        private readonly SqlSugarClient _db;
        private readonly SqlSugarClient _dbPlatform;
        private readonly SqlSugarClient _dbEngine;
        private readonly IBPMUtilsAppService _bPMUtilsApp;
        private readonly IBPMPlatformAppService _iBPMPlatformApp;
        private readonly ILogger _logger;
        private readonly IConfiguration _configuration;
        private readonly INPRestHttpHelper _nPRestHttp;
        public MaterialCheckPlanChangeService(ISqlSugarAppService sqlSugarAppService, IBPMUtilsAppService bPMUtilsApp
            , IBPMPlatformAppService iBPMPlatformApp, ILogger logger, IConfiguration configuration
            , INPRestHttpHelper nPRestHttp)
        {
            _db = sqlSugarAppService.GetBusinessInstance();
            _dbPlatform = sqlSugarAppService.GetPlatformInstance();
            _dbEngine = sqlSugarAppService.GetEngineInstance();
            _bPMUtilsApp = bPMUtilsApp;
            _iBPMPlatformApp = iBPMPlatformApp;
            _logger = logger;
            _configuration = configuration;
            _nPRestHttp = nPRestHttp;
        }

        public async Task<PagedResultDto<MaterialCheckPlanChangeOutput>> GetAllAsync(MaterialCheckPlanChangeInput input)
        {
            var listQueryable = GetQueryable(input).OrderBy(c => c.InstanceNumber, OrderByType.Desc);
            var listViewDto = await listQueryable.Skip((input.PageIndex - 1) * input.PageSize).Take(input.PageSize).ToListAsync();
            var totalCount = await listQueryable.CountAsync();

            var userId = await _iBPMPlatformApp.GetUserAsync(CurrentUser.UserName);

            listViewDto.ForEach(x =>
            {
                x.Url = _bPMUtilsApp.GetProcessUrl(x.InstanceNumber, userId);
            });

            //返回结果
            return new PagedResultDto<MaterialCheckPlanChangeOutput>()
            {
                TotalCount = totalCount,
                Items = listViewDto
            };
        }

        public async Task<List<MaterialCheckPlanChangeOutput>> ExportAsync(MaterialCheckPlanChangeInput input)
        {
            var listQueryable = GetQueryable(input).OrderBy(ins => ins.InstanceNumber, OrderByType.Desc);
            var listViewDto = await listQueryable.ToListAsync();

            return listViewDto;
        }

        private ISugarQueryable<MaterialCheckPlanChangeOutput> GetQueryable(MaterialCheckPlanChangeInput input)
        {
            var currentUserId = Guid.Empty;
            if (!input.IsQueryAll)
            {
                var currentUserDto = _dbPlatform.Queryable<Users>().Where(x => x.WorkNumber.Equals(CurrentUser.UserName)).First();
                if (currentUserDto != null)
                {
                    currentUserId = currentUserDto.UserId;
                }
            }

            var listQueryable = _db.Queryable<MaterialCheckPlanChangeHeader, BusinessProcessesNew, MaterialCheckPlanChangeDetail, MaterialCheckPlanChangeDetailChild>(
                    (x, b, d, c) => new JoinQueryInfos(JoinType.Inner, x.InstanceNumber == b.InstanceId,
                        JoinType.Inner, b.InstanceId == d.InstanceNumber, JoinType.Inner, d.Id == c.DetailId))
                .Where((x, b, d, c) => b.BTID == "MaterialCheckPlanChange")
                .Where((x, b, d, c) => c.IsRquired == "true")
                .WhereIF(!input.IsQueryAll, (x, b, d, c) => x.AddUserId.Equals(currentUserId))
                .WhereIF(!string.IsNullOrWhiteSpace(input.InstanceNumber), (x, b, d, c) => x.InstanceNumber == input.InstanceNumber)
                .WhereIF(!input.OrderStatus.IsNullOrEmpty(), (x, b, d, c) => SqlFunc.ContainsArray(input.OrderStatus.ToArray(), b.ProcessStatusCode))
                .WhereIF(!string.IsNullOrWhiteSpace(input.AddUserName), (x, b, d, c) => x.AddUserName.Contains(input.AddUserName))
                .WhereIF(input.StartCreationTime != null && input.EndCreationTime != null,
                    (x, b, d, c) => x.AddTime >= input.StartCreationTime && x.AddTime <= input.EndCreationTime)
                .WhereIF(!string.IsNullOrWhiteSpace(input.Mode), (x, b, d, c) => x.Mode == input.Mode)
                .WhereIF(!string.IsNullOrWhiteSpace(input.MaterialCode), (x, b, d, c) => d.MaterialCode.Contains(input.MaterialCode))
                .WhereIF(!string.IsNullOrWhiteSpace(input.MaterialType), (x, b, d, c) => d.MaterialType.Contains(input.MaterialType))
                .WhereIF(!string.IsNullOrWhiteSpace(input.MaterialName), (x, b, d, c) => d.MaterialName.Contains(input.MaterialName))
                .WhereIF(!string.IsNullOrWhiteSpace(input.FactoryCode), (x, b, d, c) => d.FactoryCode.Contains(input.FactoryCode))
                .WhereIF(!string.IsNullOrWhiteSpace(input.DISPO), (x, b, d, c) => d.DISPO.Contains(input.DISPO))
                .WhereIF(!string.IsNullOrWhiteSpace(input.Item), (x, b, d, c) => c.Item.Contains(input.Item))
                .Select((x, b, d, c) => new MaterialCheckPlanChangeOutput
                {
                    ChildId = c.Id,
                    InstanceNumber = d.InstanceNumber,
                    ProcessStartTime = x.AddTime,
                    ProcessStartTimeStr = x.AddTime.ToString(DateFormatHelper.DateTimeFormat),
                    ProcessStartUserName = x.AddUserName,
                    OrderStatus = b.ProcessStatusName,
                    Mode = x.Mode,
                    ModeStr = x.Mode == "1" ? "单个模式" : "批量模式",
                    MaterialCode = d.MaterialCode,
                    MaterialType = d.MaterialType,
                    MaterialTypeDesc = d.MaterialTypeDesc,
                    MaterialName = d.MaterialName,
                    FactoryCode = d.FactoryCode,
                    DISPO = d.DISPO,
                    DSNAM = d.DSNAM,
                    Item = c.Item,
                    Unit = c.Unit,
                    CheckCondition = c.CheckCondition,
                    Mininum = c.Mininum,
                    Maxnum = c.Maxnum,
                    CheckMethod = c.CheckMethod,
                    CheckFrequency = c.CheckFrequency,
                    IsRquired = c.IsRquired,
                    ChangeContent = c.ChangeContent,
                    ChangeReason = c.ChangeReason,
                });
            return listQueryable.MergeTable().Distinct();
        }

        public void FixData()
        {
            var headers = _db.Queryable<MaterialCheckPlanChangeHeader>().ToList();
            var instanceNumbers = headers.Select(x => x.InstanceNumber).ToList();
            var instances = _dbEngine.Queryable<Instances>().Where(x => instanceNumbers.Contains(x.Number)).ToList();
            foreach (var instance in instances)
            {
                var header = headers.FirstOrDefault(x => x.InstanceNumber == instance.Number);
                if (header == null)
                {
                    continue;
                }

                var instanceParams = _dbEngine.Queryable<InstanceParams>().Where(x => instance.InstanceId == x.InstanceId).ToList();
                if (instanceParams.Any())
                {
                    if (string.IsNullOrEmpty(instanceParams.FirstOrDefault(x => x.Key == "lineData")?.Value ?? ""))
                    {
                        continue;
                    }
                    var lineData = JsonConvert.DeserializeObject<List<MaterialCheckPlanChangeDetail>>(instanceParams.FirstOrDefault(x => x.Key == "lineData")?.Value ?? "");
                    // 删除附加表并插入新数据
                    _db.Deleteable<MaterialCheckPlanChangeDetail>().Where(x => x.InstanceNumber == instance.Number).ExecuteCommand();
                    var innerLineData = new List<MaterialCheckPlanChangeDetailChild>();
                    foreach (var item in lineData)
                    {
                        var detailId = Guid.NewGuid();
                        item.InstanceNumber = instance.Number;
                        item.Id = detailId;

                        // 子表详情
                        item.InnerLineData.ForEach(x =>
                        {
                            x.InstanceNumber = instance.Number;
                            x.DetailId = detailId;
                        });
                        innerLineData.AddRange(item.InnerLineData);
                    }

                    _db.Insertable(lineData).ExecuteCommand();

                    // 子表详情
                    _db.Deleteable<MaterialCheckPlanChangeDetailChild>().Where(x => x.InstanceNumber == instance.Number).ExecuteCommand();
                    _db.Insertable(innerLineData).ExecuteCommand();
                }
            }
        }
    }
}
